﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace SharpParser
{
    public static class Parsers
    {
        // 单位结构，用于表示无返回值的解析器结果
        public struct Unit
        {
            public static readonly Unit Value = new Unit();
        }

        // 解析器结果类，包含解析得到的值和剩余的输入
        public class Result<T>
        {
            public T Value { get; set; } = default!;
            public string Rest { get; set; } = null!;
        }

        // 解析器委托，接受输入字符串，返回解析结果
        public delegate Result<T>? Parser<T>(string input);

        // 解析任意字符串的解析器
        public static Parser<string> AnyString => input =>
        {
            if (string.IsNullOrEmpty(input))
                return null;
            return new Result<string> { Value = input, Rest = string.Empty };
        };

        // 解析直到遇到指定字符的解析器
        public static Parser<string> Take(Parser<string> p, char c) => input =>
        {
            var result = p(input);
            if (result == null)
                return null;
            var index = result.Value.IndexOf(c);
            if (index == -1)
                return new Result<string> { Value = result.Value, Rest = string.Empty };
            return new Result<string> { Value = result.Value.Substring(0, index), Rest = result.Value.Substring(index) };
        };

        // 解析任意字符的解析器
        public static Parser<char> AnyChar => input =>
        {
            if (string.IsNullOrEmpty(input))
                return null;
            return new Result<char> { Value = input[0], Rest = input.Substring(1) };
        };

        // 解析指定字符的解析器
        public static Parser<char> Char(char expected) => input =>
        {
            if (string.IsNullOrEmpty(input) || input[0] != expected)
                return null;
            return new Result<char> { Value = expected, Rest = input.Substring(1) };
        };

        // 顺序组合两个解析器的组合器
        public static Parser<(T1 Value1, T2 Value2)> And<T1, T2>(Parser<T1> p1, Parser<T2> p2) => input =>
        {
            var r1 = p1(input);
            if (r1 == null)
                return null;
            var r2 = p2(r1.Rest);
            if (r2 == null)
                return null;
            return new Result<(T1 Value1, T2 Value2)> { Value = (r1.Value, r2.Value), Rest = r2.Rest };
        };

        // 顺序组合三个解析器的组合器
        public static Parser<(T1 Value1, T2 Value2, T3 Value3)> And<T1, T2, T3>(Parser<T1> p1, Parser<T2> p2, Parser<T3> p3) => input =>
        {
            var r1 = p1(input);
            if (r1 == null)
                return null;
            var r2 = p2(r1.Rest);
            if (r2 == null)
                return null;
            var r3 = p3(r2.Rest);
            if (r3 == null)
                return null;
            return new Result<(T1 Value1, T2 Value2, T3 Value3)> { Value = (r1.Value, r2.Value, r3.Value), Rest = r2.Rest };
        };

        // 顺序组合五个解析器的组合器
        public static Parser<(T1 Value1, T2 Value2, T3 Value3, T4 Value4, T5 Value5)> And<T1, T2, T3, T4, T5>(
            Parser<T1> p1, Parser<T2> p2, Parser<T3> p3, Parser<T4> p4, Parser<T5> p5)
            => input =>
            {
                var r1 = p1(input);
                if (r1 == null)
                    return null;
                var r2 = p2(r1.Rest);
                if (r2 == null)
                    return null;
                var r3 = p3(r2.Rest);
                if (r3 == null)
                    return null;
                var r4 = p4(r3.Rest);
                if (r4 == null)
                    return null;
                var r5 = p5(r4.Rest);
                if (r5 == null)
                    return null;
                return new Result<(T1, T2, T3, T4, T5)>
                {
                    Value = (r1.Value, r2.Value, r3.Value, r4.Value, r5.Value),
                    Rest = r5.Rest
                };
            };

        // 选择两个解析器中的一个的组合器
        public static Parser<T> Or<T>(Parser<T> p1, Parser<T> p2) => input =>
        {
            var r1 = p1(input);
            if (r1 != null)
                return r1;
            return p2(input);
        };

        // 重复解析零次或多次的组合器
        public static Parser<List<T>> ZeroOrMore<T>(Parser<T> p) => input =>
        {
            var values = new List<T>();
            var rest = input;
            while (true)
            {
                var r = p(rest);
                if (r == null)
                    break;
                values.Add(r.Value);
                rest = r.Rest;
            }
            return new Result<List<T>> { Value = values, Rest = rest };
        };

        // 重复解析一次或多次的组合器
        public static Parser<List<T>> OneOrMore<T>(Parser<T> p) => input =>
        {
            var r = p(input);
            if (r == null)
                return null;
            var values = new List<T> { r.Value };
            var rest = r.Rest;
            while (true)
            {
                r = p(rest);
                if (r == null)
                    break;
                values.Add(r.Value);
                rest = r.Rest;
            }
            return new Result<List<T>> { Value = values, Rest = rest };
        };

        // 解析失败的组合器
        public static Parser<Unit> Not<T>(Parser<T> p) => input =>
        {
            var r = p(input);
            if (r == null)
                return new Result<Unit> { Value = Unit.Value, Rest = input };
            return null;
        };

        // 解析直到遇到指定字符，且不包含该字符的解析器
        public static Parser<string> Until(Parser<string> p, char c) => input =>
        {
            var result = p(input);
            if (result == null)
                return null;
            var index = result.Value.IndexOf(c);
            if (index == -1)
                return new Result<string> { Value = result.Value, Rest = string.Empty };
            return new Result<string> { Value = result.Value.Substring(0, index), Rest = result.Value.Substring(index + 1) };
        };

        // 解析并忽略结果的组合器
        public static Parser<Unit> Skip<T>(Parser<T> p) => input =>
        {
            var r = p(input);
            if (r == null)
                return null;
            return new Result<Unit> { Value = Unit.Value, Rest = r.Rest };
        };

        // 重复解析指定次数的组合器
        public static Parser<List<T>> Repeat<T>(Parser<T> p, int count) => input =>
        {
            var values = new List<T>();
            var rest = input;
            for (int i = 0; i < count; i++)
            {
                var r = p(rest);
                if (r == null)
                    return null;
                values.Add(r.Value);
                rest = r.Rest;
            }
            return new Result<List<T>> { Value = values, Rest = rest };
        };

        // 解析可选的值的解析器
        public static Parser<T> Optional<T>(Parser<T> p, T defaultValue = default) => input =>
        {
            var r = p(input);
            if (r != null)
                return r;
            return new Result<T> { Value = defaultValue, Rest = input };
        };

        // 解析空白字符的解析器
        public static Parser<string> WhiteSpace => input =>
        {
            var match = Regex.Match(input, @"^\s+");
            if (!match.Success)
                return null;
            return new Result<string> { Value = match.Value, Rest = input.Substring(match.Length) };
        };

        // 解析一行的解析器
        public static Parser<string> Line => Take(AnyString, '\n');

        // 解析一个标记（非空白字符序列）的解析器
        public static Parser<string> Token => input =>
        {
            var match = Regex.Match(input, @"^\S+");
            if (!match.Success)
                return null;
            return new Result<string> { Value = match.Value, Rest = input.Substring(match.Length) };
        };
    }
}
